using System;
using System.Diagnostics;

namespace Heaven.Engine.Animation
{
    /// <summary>
    /// This is clock which controlls animation process
    /// </summary>
    public class Clock
    {
        #region Events

        /// <summary>
        /// Occurs when ration is changed
        /// </summary>
        public event EventHandler RatioChanged;

        /// <summary>
        /// Occurs when the clock is started/resumed
        /// </summary>
        public event EventHandler Started;

        /// <summary>
        /// Occurs when the clock is stopped/paused
        /// </summary>
        public event EventHandler Stopped;

        #endregion

        #region Fields

        // A number of milliseconds at last time
        double previous = 0;
        // Current value, ms
        double milliseconds = 0;
        // Indicates whether this Clock is paused
        bool paused = true;
        // Speed factor
        double ratio = 1.0;

        #endregion

        #region Properties

        /// <summary>
        /// Indicates whether this Clock is paused
        /// </summary>
        public bool IsPaused
        {
            get { return paused; }
        }
        
        /// <summary>
        /// Current amount of elapsed milliseconds 
        /// </summary>
        public double Milliseconds
        {
            get 
            {                
                UpdateMilliseconds();
                return milliseconds; 
            }
            set
            {
                if (!paused)
                {
                    previous = Environment.TickCount;
                }
                milliseconds = value;
            }
        }

        void UpdateMilliseconds()
        {
            if (!paused)
            {
                int tickCount = Environment.TickCount;
                milliseconds += (double)(tickCount - previous) * ratio;
                previous = tickCount;
            }
        }

        /// <summary>
        /// Speed factor. You can set -1.0 
        /// to perform reverse measuring
        /// </summary>
        public double Ratio
        {
            get { return ratio; }
            set 
            { 
                ratio = value;
                if (RatioChanged != null) RatioChanged(this, EventArgs.Empty);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Starts, or resumes, measuring time
        /// (reset current time)
        /// </summary>
        public void Start()
        {
            Milliseconds = 0.0;
            previous = Environment.TickCount;
            paused = false;

            if (Started != null) Started(this, EventArgs.Empty);
        }

        /// <summary>
        /// Stops measuring time
        /// </summary>
        public void Pause()
        {
            UpdateMilliseconds();
            paused = true;

            if (Stopped != null) Stopped(this, EventArgs.Empty);
        }

        /// <summary>
        /// Resumes measuring time
        /// </summary>
        public void Resume()
        {
            previous = Environment.TickCount;
            paused = false;

            if (Started != null) Started(this, EventArgs.Empty);
        }

        /// <summary>
        /// Stops measuring time
        /// (reset current time)
        /// </summary>
        public void Stop()
        {
            Milliseconds = 0.0;
            paused = true;

            if (Stopped != null) Stopped(this, EventArgs.Empty);
        }

        #endregion
    }

    /*
/// <summary>
    /// This is clock which controlls animation process
    /// </summary>
    public class Clock
    {
        #region Events

        /// <summary>
        /// Occurs when ration is changed
        /// </summary>
        public event EventHandler RatioChanged;

        /// <summary>
        /// Occurs when the clock is started/resumed
        /// </summary>
        public event EventHandler Started;

        /// <summary>
        /// Occurs when the clock is stopped/paused
        /// </summary>
        public event EventHandler Stopped;

        #endregion

        #region Fields

        // Provides elapsed time
        Stopwatch stopwatch = new Stopwatch();
        // Current value, ms
        double milliseconds = 0;
        // Indicates whether this Clock is paused
        bool paused = true;
        // Speed factor
        double ratio = 1.0;

        #endregion

        #region Properties

        /// <summary>
        /// Indicates whether this Clock is paused
        /// </summary>
        public bool IsPaused
        {
            get { return paused; }
        }
        
        /// <summary>
        /// Current amount of elapsed milliseconds 
        /// </summary>
        public double Milliseconds
        {
            get 
            {                
                UpdateMilliseconds();
                return milliseconds; 
            }
            set
            {
                if (!paused)
                {
                    stopwatch.Reset();
                    stopwatch.Start();
                }
                milliseconds = value;
            }
        }

        void UpdateMilliseconds()
        {
            if (!paused)
            {
                milliseconds += (double)(stopwatch.ElapsedMilliseconds) * ratio;
                stopwatch.Reset();
                stopwatch.Start();
            }
        }

        /// <summary>
        /// Speed factor. You can set -1.0 
        /// to perform reverse measuring
        /// </summary>
        public double Ratio
        {
            get { return ratio; }
            set 
            { 
                ratio = value;
                if (RatioChanged != null) RatioChanged(this, EventArgs.Empty);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Starts, or resumes, measuring time
        /// (reset current time)
        /// </summary>
        public void Start()
        {
            Milliseconds = 0.0;
            paused = false;

            if (Started != null) Started(this, EventArgs.Empty);
        }

        /// <summary>
        /// Stops measuring time
        /// </summary>
        public void Pause()
        {
            UpdateMilliseconds();
            stopwatch.Stop();
            paused = true;

            if (Stopped != null) Stopped(this, EventArgs.Empty);
        }

        /// <summary>
        /// Resumes measuring time
        /// </summary>
        public void Resume()
        {
            stopwatch.Start();
            paused = false;

            if (Started != null) Started(this, EventArgs.Empty);
        }

        /// <summary>
        /// Stops measuring time
        /// (reset current time)
        /// </summary>
        public void Stop()
        {
            Milliseconds = 0.0;
            paused = true;

            if (Stopped != null) Stopped(this, EventArgs.Empty);
        }

        #endregion
    }*/
}
